package net.omnivention.proxy;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import org.apache.log4j.Logger;

public class ClientToHost implements Runnable {
	private static Logger logger = Logger.getLogger(ClientToHost.class);

	private Socket clientSocket;

	private Socket hostSocket;

	private long timeout = 12000;

	private HttpRequest request;

	private SSLSocketFactory socketFactory;

	public ClientToHost(HttpRequest request, Socket clientSocket, Socket hostSocket) {
		this.request = request;
		this.clientSocket = clientSocket;
		this.hostSocket = hostSocket;
		socketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
	}

	public void run() {
		try {
			String method = request.getMethod();
			if (HttpRequest.CONNECT.equals(method)) {
				interceptDataStreamForwardToHost();
				// streamDataFromClientToHost();
			} else {
				OutputStream hostOutputStream = hostSocket.getOutputStream();
				hostOutputStream.write(request.getAsByteArray());
				hostOutputStream.flush();
				logger.debug("\n" + request);
			}
		} catch (IOException ex) {
			logger.error(ex,ex);		
		}
	}

	private void interceptDataStreamForwardToHost() throws IOException{
		SSLSocket sslClientSocket = (SSLSocket) socketFactory.createSocket(clientSocket,clientSocket.getInetAddress().getHostName(),clientSocket.getPort(),true);
		sslClientSocket.setUseClientMode(false);
		InputStream clientInputStream = sslClientSocket.getInputStream();
		
		HttpRequest r = HttpUtility.parseRequest(clientInputStream);
		
		SSLSocket destSocket = (SSLSocket) socketFactory.createSocket(request.getHost(),request.getPort());
		destSocket.setUseClientMode(false);
		OutputStream hostOutputStream = destSocket.getOutputStream();
		hostOutputStream.write(r.getAsByteArray());
		hostOutputStream.flush();
		logger.debug("\n" + r);
	}

	private void streamDataStraightToHost() throws IOException {
		InputStream clientInputStream = clientSocket.getInputStream();
		BufferedInputStream clientBufferedInputStream = new BufferedInputStream(clientInputStream);

		OutputStream hostOutStream = hostSocket.getOutputStream();
		BufferedOutputStream hostBufferedOutputStream = new BufferedOutputStream(hostOutStream);

		long delta = 0;
		long time0 = System.currentTimeMillis(), time1 = 0;

		while (delta < timeout) {
			int avail = clientBufferedInputStream.available();
			if (avail > 0) {
				byte[] data = new byte[avail];
				clientBufferedInputStream.read(data);
				hostBufferedOutputStream.write(data);
				hostBufferedOutputStream.flush();
			} else {
				time1 = System.currentTimeMillis();
				delta = time1 - time0;
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
				}
			}
		}
	}

}
